package com.mmall.service.impl;

import com.mmall.common.IConst;
import com.mmall.common.ResponseInfo;
import com.mmall.common.ServerResponse;
import com.mmall.common.TokenCache;
import com.mmall.dao.UserMapper;
import com.mmall.pojo.User;
import com.mmall.service.IUserService;
import com.mmall.util.MD5Util;
import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.stereotype.Service;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.UUID;

/**
 * 用户信息Service实现类
 * Created by Administrator on 2017/9/21-23:50.
 */
@Service("iUserService")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class UserServiceImpl implements IUserService {

    @Resource
    private UserMapper userMapper;

    @Override
    public ServerResponse<User> login(String username, String password) {
        int resultCount = userMapper.checkUsername(username);
        if (resultCount == 0) return ServerResponse.createByErrorMessage("用户名不存在");

        //todo 密码登陆MD5
        String MD5 = MD5Util.MD5EncodeUtf8(password);
        User user = userMapper.selectLogin(username, MD5);
        if (user == null) return ServerResponse.createByErrorMessage("密码错误");

        //将用户密码置空
        user.setPassword(StringUtils.EMPTY);
        return ServerResponse.createBySuccess("登陆成功", user);
    }

    @Override
    public ServerResponse<String> checkValid(String field, String type) {
        if (StringUtils.isBlank(type)) return ServerResponse.createByErrorMessage("请指定信息类型!");
        switch (type.toLowerCase().trim()) {
            case IConst.USERNAME:
                int i = userMapper.checkUsername(field);
                if (i > 0) return ServerResponse.createByErrorMessage("用户名已存在!");
                break;
            case IConst.EMAIL:
                int i1 = userMapper.checkEmail(field);
                if (i1 > 0) return ServerResponse.createByErrorMessage("邮箱已被注册!");
                break;
            case IConst.TELEPHONE:
                int i2 = userMapper.checkPhone(field);
                if (i2 > 0) return ServerResponse.createByErrorMessage("手机号码已被注册!");
                break;
            default:
                return ServerResponse.createByErrorMessage("请输入正确的信息类型!");
        }
        return ServerResponse.createBySuccess();
    }

    @Override
    public ServerResponse<String> register(User user) {
        ServerResponse<String> validResponse = checkValid(user.getUsername(), IConst.USERNAME);
        System.out.println("==========");
        if (!validResponse.isSuccess()) return validResponse;
        validResponse = checkValid(user.getEmail(), IConst.EMAIL);
        if (!validResponse.isSuccess()) return validResponse;
        validResponse = checkValid(user.getPhone(), IConst.TELEPHONE);
        if (!validResponse.isSuccess()) return validResponse;

        user.setRole(IConst.Role.CUSTOMER);
        //密码MD5加密保存到数据库
        user.setPassword(MD5Util.MD5EncodeUtf8(user.getPassword()));

        int insertCount = userMapper.insert(user);
        if (insertCount == 0) return ServerResponse.createByErrorMessage("注册失败!");
        return ServerResponse.createBySuccessMessage("注册成功!");
    }

    @Override
    public ServerResponse<String> selectQuestion(String username) {
        ServerResponse<String> response = checkValid(username, IConst.USERNAME);
        if (response.isSuccess()) return ServerResponse.createByErrorMessage("用户名不存在");
        String question = userMapper.selectQuestionByUsername(username);
        //org.apache.commons.lang3.StringUtils工具类中isNotBlank和isNotEmpty的区别在于:
        // 对于" "的判定,isNotBlank为false,isNotEmpty为true
        if (StringUtils.isNotBlank(question)) return ServerResponse.createBySuccess(question);
        return ServerResponse.createByErrorMessage("找回密码的问题为空!");
    }

    @Override
    public ServerResponse<String> checkAnswer(String username, String question, String answer) {
        int resultCount = userMapper.checkAnswer(username, question, answer);
        if (resultCount > 0) {
            //生成并传递token和保存token到缓存.
            String forgetToken = UUID.randomUUID().toString();
            TokenCache.setKey(TokenCache.TOKEN_PREFIEX + username, forgetToken);
            return ServerResponse.createBySuccess(forgetToken);
        }
        return ServerResponse.createByErrorMessage("问题的答案错误!");
    }

    @Override
    public ServerResponse<String> forgetResetPassword(String username, String passwordNew, String forgetToken) {
        if (StringUtils.isBlank(forgetToken))
            return ServerResponse.createByErrorMessage("参数错误,缺少需要传递的token!");
        //验证用户名是否存在
        ServerResponse<String> response = checkValid(username, IConst.USERNAME);
        if (response.isSuccess()) return ServerResponse.createByErrorMessage("用户名不存在");
        String token = TokenCache.getKey(TokenCache.TOKEN_PREFIEX + username);
        if (StringUtils.isBlank(token))
            return ServerResponse.createByErrorMessage("token无效或已过期!");
        if (StringUtils.equals(forgetToken, token)) {
            System.out.println(passwordNew);
            String md5Password = MD5Util.MD5EncodeUtf8(passwordNew);
            int rowCount = userMapper.updatePasswordByUsername(username, md5Password);
            if (rowCount > 0)
                return ServerResponse.createBySuccessMessage("修改密码成功!");
        } else return ServerResponse.createByErrorMessage("token错误,请重新操作!");
        return ServerResponse.createByErrorMessage("修改密码失败!");
    }

    @Override
    public ServerResponse<String> resetPassword(String passwordOld, String passwordNew, User user) {
        //防止横向越权,要校验一下这个用户的旧密码,且一定要指定该用户.
        int resultCount = userMapper.checkPassword(MD5Util.MD5EncodeUtf8(passwordOld), user.getId());
        if (resultCount == 0)
            return ServerResponse.createByErrorMessage("旧密码错误!");

        user.setPassword(MD5Util.MD5EncodeUtf8(passwordNew));
        //考虑到类字段的扩展性,推荐使用选择属性的更新方法,而不是全部字段更新方法.
        // 否则在对类进行扩展的时候,由于新添加的字段在旧代码中没有设置,会被自动设置为null,
        //并更新到数据表中.
        int updateCount = userMapper.updateByPrimaryKeySelective(user);
        if (updateCount > 0)
            return ServerResponse.createBySuccessMessage("更新密码成功!");
        return ServerResponse.createByErrorMessage("更新密码失败!");
    }

    @Override
    public ServerResponse<User> updateInfo(User newUser) {
        //不更改用户名,用户id
        //判定用户字段信息是否被使用时,需要在sql语句中排除该用户本身.
        //所以不能直接使用注册时的查询sql语句
        int resultCount = userMapper.checkEmailWithoutId(newUser.getEmail(), newUser.getId());
        if (resultCount > 0)
            return ServerResponse.createByErrorMessage("email已存在,请更换email再尝试更新");
        int resultCount2 = userMapper.checkEmailWithoutId(newUser.getPhone(), newUser.getId());
        if (resultCount2 > 0)
            return ServerResponse.createByErrorMessage("手机号码已存在,请更换手机号码再尝试更新");
        //这里老师是重新新建了一个User对象,然后将要更新的字段一个个添加到了其中.
        //开始我感觉这种方法很麻烦,但是细想一下.
        //如果直接传递前台的信息封装的对象,如果对方在信息中传递了一个密码等等不需要更新的数据.
        //那就把不需要更新的字段也修改掉了.
        //而且这种方法可以减少userId,userName这类不更新信息的更新
        //所以貌似还是老师这种方法好
        int i = userMapper.updateByPrimaryKeySelective(newUser);
        if (i > 0) return ServerResponse.createBySuccess("更新用户信息成功", newUser);
        return ServerResponse.createByErrorMessage("更新用户信息失败!");
    }

    @Override
    public ServerResponse<User> getInfo(int userId) {
        User user = userMapper.getInfo(userId);
        if (user == null) return ServerResponse.createByErrorMessage("找不到当前用户!");
        user.setPassword(StringUtils.EMPTY);
        return ServerResponse.createBySuccess(user);
    }

    /**
     * 校验用户是否为管理员身份
     *
     * @param user 用户信息
     * @return 响应对象
     */
    @Override
    public ServerResponse adminCheck(User user) {
        if (user != null && user.getRole() == IConst.Role.ADMIN)
            return ServerResponse.createBySuccessMessage("已验证管理员身份!");
        return ServerResponse.createByErrorMessage("该用户无操作权限!");
    }

    /**
     * 我自己重新包装的验证管理员身份的方法
     *
     * @param session 当前回话
     * @return 响应对象
     */
    @Override
    public ServerResponse adminCheck(HttpSession session) {
        User user = (User) session.getAttribute(IConst.CURRENT_USER);
        if (user == null)
            return ServerResponse.createByErrorCode(ResponseInfo.NEED_LOGIN.getCode(), "用户未登录,请重新登录!");
        return adminCheck(user);
    }

    @Test
    public void tt() {
        login("22", "33");
    }

}
